# admin.py
# Author: Nico Marrero
# Copyright 2012 Nico Marrero
#
#	 This file is part of django-serenity.
#
#    django-serenity is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    django-serenity is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with django-serenity.  If not, see <http://www.gnu.org/licenses/>.

from models import SerenityArmor, SerenityAssetComplication, SerenityCharacter, SerenityCharacterForm
from models import SerenityCharacterAsset, SerenityCharacterComplication, SerenityCharacterAssetForm, SerenityCharacterComplicationForm
from models import SerenityCharacterSkillSpecialty, SerenityWeapon, SerenityDiceRoller
from models import SerenityCharacterArmor, SerenityCharacterWeapon, SerenityAdventureLog

from django.shortcuts import HttpResponseRedirect, Http404
from django.core.urlresolvers import reverse
from django.utils.functional import lazy
from django.contrib import admin, messages
from django.forms.models import model_to_dict
from django.utils.encoding import force_unicode

def reroll(modeladmin, request, queryset):
	for roll in queryset:
		roll.roll()
reroll.short_description = "Reroll the selected dice rolls"
def repeat_dice_roll(modeladmin, request, queryset):
	for roll in queryset:
		NewRoll = roll.clone()
		NewRoll.player = request.user
		NewRoll.roll()
repeat_dice_roll.short_description = "Roll a copy of selected dice rolls"
def approve_character(modeladmin, request, queryset):
	if request.user.has_perm('serenity.approve_serenitycharacter'):
		queryset.filter(approved_by=None).update(approved_by=request.user)
approve_character.short_description = "Approve selected characters"
def unapprove_character(modeladmin, request, queryset):
	if request.user.has_perm('serenity.approve_serenitycharacter'):
		queryset.update(approved_by=None)
unapprove_character.short_description = "Unapprove selected characters"

class SerenityCharacterAdmin(admin.ModelAdmin):
	list_display = ['nickname', 'name', 'approved', 'alive', 'conscious']
	list_display_links = ['nickname', 'name']
	actions = [approve_character, unapprove_character]
	form = SerenityCharacterForm
	def get_actions(self, request):
		actions = super(SerenityCharacterAdmin,self).get_actions(request)
		if not request.user.has_perm('serenity.approve_serenitycharacter'):
			if 'approve_character' in actions:
				del actions['approve_character']
			if 'unapprove_character' in actions:
				del actions['unapprove_character']
		if not request.user.has_perm('serenity.delete_serenitycharacter'):
			if 'delete_selected' in actions:
				del actions['delete_selected']
		return actions
	def response_change(self, request, obj):
		return HttpResponseRedirect(reverse('admin:serenity_serenitycharacter_change',args=[obj.id]))
	def save_model(self, request, obj, form, change):
		if not obj.player or not request.user.has_perm('serenity.change_all_serenitycharacters'):
			obj.player = request.user
		obj.save()
		if not SerenityCharacterArmor.objects.filter(character=obj):
			SerenityCharacterArmor(character=obj).save()
		if not SerenityCharacterWeapon.objects.filter(character=obj):
			SerenityCharacterWeapon(character=obj).save()
	def get_extra_context(self, request,object_id=None):
		if object_id: TheCharacter = self.get_object(request,object_id)
		else: TheCharacter = SerenityCharacter(player=request.user)
		
		if not TheCharacter: raise Http404
		
		TheCharacterDict = model_to_dict(TheCharacter,self.fields,self.exclude)
		for field in TheCharacterDict:
			if hasattr(TheCharacter,"get_%s_display" % field):
				TheCharacterDict[field] = getattr(TheCharacter,"get_%s_display" % field)()
				if TheCharacterDict[field] == '0': TheCharacterDict[field] = "None"
		Assets = TheCharacter.assets.all()
		Complications = TheCharacter.complications.all()
		
		Specialties = {}
		for specialty in TheCharacter.specialties.all():
			if not specialty.skill in Specialties: Specialties[specialty.skill] = []
			Specialties[specialty.skill].append(specialty)
		Weapon = SerenityCharacterWeapon.objects.filter(character=TheCharacter)
		Armor = SerenityCharacterArmor.objects.filter(character=TheCharacter)
		context_dict = {
			'AdventureLogs':SerenityAdventureLog.objects.order_by('-date'),
			'Character':TheCharacter,
			'CharacterDict':TheCharacterDict,
			'Assets':Assets,
			'Complications':Complications,
			'Specialties':Specialties,
			'Weapon': Weapon[0] if Weapon else None,
			'Armor': Armor[0] if Armor else None,
			'show_specific_fields':['player','equipment','credits','nickname','description','notes','history'],
		}
		return context_dict
	def changelist_view(self, request, *args, **kwargs):
		if not 'extra_context' in kwargs: kwargs['extra_context'] = {} 
		kwargs['extra_context'].update(self.get_extra_context(request))
		return super(SerenityCharacterAdmin, self).changelist_view(request, *args, **kwargs)
	def add_view(self, request, *args, **kwargs):
		if not 'extra_context' in kwargs: kwargs['extra_context'] = {} 
		kwargs['extra_context'].update(self.get_extra_context(request))
		return super(SerenityCharacterAdmin, self).add_view(request, *args, **kwargs)
	def change_view(self, request, object_id, *args, **kwargs):
		if not 'extra_context' in kwargs: kwargs['extra_context'] = {}
		kwargs['extra_context'].update(self.get_extra_context(request,object_id))
		return super(SerenityCharacterAdmin, self).change_view(request, object_id, *args, **kwargs)
	def queryset(self, request):
		"""
		Filter the objects displayed in the change_list to only
		display those for the currently signed in user.
		"""
		qs = super(SerenityCharacterAdmin, self).queryset(request)
		if request.user.has_perm('serenity.change_all_serenitycharacters'):
			return qs
		return qs.filter(player=request.user)

class SerenityCharacterItemAdmin(admin.ModelAdmin):
	def get_form(self, request, obj=None, **kwargs):
		self.exclude = self.exclude if self.exclude else [] + ['character'] #When creating a character, the player is set
		return super(SerenityCharacterItemAdmin, self).get_form(request, obj, **kwargs)
	def response_change(self, request, obj):
		return HttpResponseRedirect(reverse('admin:serenity_serenitycharacter_change',args=[obj.character.id]))
	def get_model_perms(self,request):
		perms = super(SerenityCharacterItemAdmin, self).get_model_perms(request)
		if not request.user.has_perm('serenity.change_all_serenitycharacters'):
			perms['list_hide'] = True
		return perms
	def formfield_for_foreignkey(self, db_field, request, **kwargs):
		if db_field.name == "character" and not request.user.has_perm('serenity.change_all_serenitycharacters'):
			kwargs["queryset"] = SerenityCharacter.objects.filter(player=request.user)
		return super(SerenityCharacterItemAdmin,self).formfield_for_foreignkey(db_field, request, **kwargs)
	def queryset(self, request):
		"""
		Filter the objects displayed in the change_list to only
		display those for the currently signed in user.
		"""
		qs = super(SerenityCharacterItemAdmin, self).queryset(request)
		if request.user.has_perm('serenity.change_all_serenitycharacters'):
			return qs
		return qs.filter(character__player=request.user)

class SerenityWeaponAdmin(admin.ModelAdmin):
	list_display = ['name','type','damage','range','rate','ammo']
	list_filter = ['type']

class SerenityArmorAdmin(admin.ModelAdmin):
	list_display = ['name','type','rating','covers','penalty']
	list_filter = ['type']
	
class SerenityAssetComplicationAdmin(admin.ModelAdmin):
	list_display = ['type', 'short_name', 'enabled', 'original', 'description']
	list_filter = ['type','enabled','original','level','double_cost','requires_specialization']
	list_display_links = ['short_name']
	list_editable = ['enabled']

class SerenityCharacterAssetComplicationAdmin(admin.ModelAdmin):
	def get_model_perms(self,request):
		perms = super(SerenityCharacterAssetComplicationAdmin, self).get_model_perms(request)
		if not request.user.has_perm('serenity.change_all_serenitycharacters'):
			perms['list_hide'] = True
		return perms
	def formfield_for_foreignkey(self, db_field, request, **kwargs):
		if db_field.name == "character" and not request.user.has_perm('serenity.change_all_serenitycharacters'):
			kwargs["queryset"] = SerenityCharacter.objects.filter(player=request.user)
		return super(SerenityCharacterAssetComplicationAdmin,self).formfield_for_foreignkey(db_field, request, **kwargs)
	def queryset_filter(self, qs):
		return qs
	def queryset(self, request):
		"""
		Filter the objects displayed in the change_list to only
		display those for the currently signed in user.
		"""
		qs = super(SerenityCharacterAssetComplicationAdmin, self).queryset(request)
		if request.user.has_perm('serenity.change_all_serenitycharacters'):
			return self.queryset_filter(qs)
		return self.queryset_filter(qs.filter(character__player=request.user).filter(character__approved_by=None))

class SerenityCharacterAssetAdmin(SerenityCharacterAssetComplicationAdmin):
	form = SerenityCharacterAssetForm
	list_display = ['character','asset_name','specialization','asset_effect']
	def queryset_filter(self, qs):
		return qs.filter(asset__type='asset')
		
class SerenityCharacterComplicationAdmin(SerenityCharacterAssetComplicationAdmin):
	form = SerenityCharacterComplicationForm
	list_display = ['character','complication_name','specialization','complication_effect']
	def queryset_filter(self, qs):
		return qs.filter(complication__type='complication')
	
class SerenityDiceRollerAdmin(admin.ModelAdmin):
	actions = [reroll, repeat_dice_roll]
	list_display = ['__unicode__','result','__results__','created']
	list_display_links = ['__unicode__']
	ordering = ['-created']
	def get_actions(self, request):
		actions = super(SerenityDiceRollerAdmin,self).get_actions(request)
		if not request.user.has_perm('serenity.reroll_serenitydiceroller'):
			if 'reroll' in actions:
				del actions['reroll']
		if not request.user.has_perm('serenity.delete_serenitydiceroller'):
			if 'delete_selected' in actions:
				del actions['delete_selected']
		return actions
	def change_view(self, request, object_id, *args, **kwargs):
		if request.user.has_perm('serenity.change_all_serenitydiceroller'):
			return super(SerenityDiceRollerAdmin, self).change_view(request, object_id, *args, **kwargs)
		return HttpResponseRedirect(reverse('admin:serenity_serenitydiceroller_changelist'))
	def changelist_view(self, request, *args, **kwargs):
		if not request.user.has_perm('serenity.change_all_serenitydiceroller'):
			self.list_display_links = (None,)
		return super(SerenityDiceRollerAdmin, self).changelist_view(request, *args, **kwargs)
	def save_model(self, request, obj, form, change):
		obj.player = request.user
		if not obj.id:
			messages.info(request, "Dice Roller result: %s" % obj.roll())
		else:
			obj.save()
	def queryset(self, request):
		"""
		Filter the objects displayed in the change_list to only
		display those for the currently signed in user.
		"""
		qs = super(SerenityDiceRollerAdmin, self).queryset(request)
		if request.user.has_perm('serenity.change_all_serenitydiceroller'):
			return qs
		return qs.filter(player=request.user)

class SerenityAdventureLogAdmin(admin.ModelAdmin):
	list_display = ['title','date','author','initial_text']
	class Media:
		js = [lazy(reverse,str)('tinymce-compressor'),
			  'js/textareas_gzip.js',
			  'js/textareas.js']
	def get_model_perms(self, request):
		perms = super(SerenityAdventureLogAdmin,self).get_model_perms(request)
		if not request.user.has_perm('serenity.add_serenityadventurelog'):
			perms['list_hide'] = True
		return perms
	def changelist_view(self, request, *args, **kwargs):
		if not request.user.has_perm('serenity.change_all_serenityadventurelogs'):
			if 'author' in self.list_display:
				self.list_display.remove('author')
		return super(SerenityAdventureLogAdmin, self).changelist_view(request, *args, **kwargs)
	def save_model(self, request, obj, form, change):
		if not obj.author:
			obj.author = request.user
		obj.save()
	def queryset(self, request):
		"""
		Filter the objects displayed in the change_list to only
		display those for the currently signed in user.
		"""
		qs = super(SerenityAdventureLogAdmin, self).queryset(request)
		if request.user.has_perm('serenity.change_all_serenityadventurelogs'):
			print "User has perm %s" % request.user
			return qs
		return qs.filter(author=request.user)

class SerenityCharacterSkillSpecialtyAdmin(admin.ModelAdmin):
	def get_model_perms(self, request):
		perms = super(SerenityCharacterSkillSpecialtyAdmin,self).get_model_perms(request)
		if not request.user.has_perm('serenity.change_all_serenitycharacters'):
			perms['list_hide'] = True
		return perms
admin.site.register(SerenityAdventureLog, SerenityAdventureLogAdmin)
admin.site.register(SerenityArmor, SerenityArmorAdmin)
admin.site.register(SerenityAssetComplication, SerenityAssetComplicationAdmin)
admin.site.register(SerenityCharacter,SerenityCharacterAdmin)
admin.site.register(SerenityCharacterAsset, SerenityCharacterAssetAdmin)
admin.site.register(SerenityCharacterComplication, SerenityCharacterComplicationAdmin)
admin.site.register(SerenityCharacterWeapon, SerenityCharacterItemAdmin)
admin.site.register(SerenityCharacterArmor, SerenityCharacterItemAdmin)
admin.site.register(SerenityCharacterSkillSpecialty, SerenityCharacterSkillSpecialtyAdmin)
admin.site.register(SerenityWeapon, SerenityWeaponAdmin)
admin.site.register(SerenityDiceRoller,SerenityDiceRollerAdmin)